package cuatroenraya.jugadores;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import cuatroenraya.Jugador;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Laurita
 */
public class JugadorAlumnoG30 extends Jugador
{

    private int filas = 8;
    private int columnas = 8;
    private int lugarVacio = 0;
    private boolean primeraFicha = true;

    private int[] jugadaMia;
    private int[] jugadaRival;

    private int[][][] estados;
    private int[][] heuristicas;
    
    private int[][][] estadosRival;
    private int[][] heuristicasRival;

    @Override
    public int[] jugar(int[][] tablero)
    {

        if (primeraFicha)
        {
            primeraFicha = false;
            Random rnd = new Random();
            int[] jugada = new int[2];
            jugada[0] = (int) (rnd.nextDouble() * 7);
            jugada[1] = (int) (rnd.nextDouble() * 7);
            return jugada;
        }

        int[][] auxTablero = new int[filas][columnas];
        for(int i = 0; i<filas; i++)
        {
            for(int j = 0; j<columnas; j++)
            {
                auxTablero[i][j] = tablero[i][j]; 
            }
        }
        
        generarEstados(auxTablero, estados, heuristicas,1,2);

        for(int i = 0; i<filas; i++)
        {
            for(int j = 0; j<columnas; j++)
            {
                auxTablero[i][j] = tablero[i][j];
            }
        }
        
        generarEstados(auxTablero,estadosRival,heuristicasRival,2,1);
        
        int[] jugada = new int[2];
        if(jugadaMia[2]>=jugadaRival[2])
        {
            jugada[0] = jugadaMia[0];
            jugada[1] = jugadaMia[1];
        }
        else
        {
            jugada[0] = jugadaRival[0];
            jugada[1] = jugadaRival[1];
        }
        return jugada;
    }
    
    private void generarEstados(int[][] tablero, int[][][] pEstados, int[][] pHeuristicas, int pFicha, int pFichaRival)
    {
        int cantEspaciosVacios = espaciosVacios(tablero);
        pEstados = new int[cantEspaciosVacios][filas][columnas];
        pHeuristicas = new int[cantEspaciosVacios][3];
        boolean estadoGenerado = false;

        int[][] tableroInicial = new int[filas][columnas];
        for (int i = 0; i < filas; i++)
        {
            for (int j = 0; j < columnas; j++) 
            {
                tableroInicial[i][j] = tablero[i][j];
            }
        }

        int columna = 0;
        int fila = 0;
        for (int estado = 0; estado < cantEspaciosVacios; estado++) 
        {
            int posicionJ = 0;
            int[][] aux = new int[filas][columnas];
            for (int i = 0; i < filas; i++)
            {
                for (int j = 0; j < columnas; j++)
                {
                    aux[i][j] = tableroInicial[i][j];
                }
            }

            pEstados[estado] = aux;

            for (int i = fila; i < filas; i++) 
            {
                for (int j = 0; j < columnas; j++) 
                {
                    if (tablero[i][j] == lugarVacio) 
                    {
                        tablero[i][j] = pFicha;
                        pEstados[estado][i][j] = pFicha;
                        posicionJ = j;
                        estadoGenerado = true;
                        columna = j + 1;
                        break;
                    }
                }
                if (columna == columnas) 
                {
                    fila = i + 1;
                }
                if (estadoGenerado)
                {
                    calcularHeuristica(i,posicionJ,pEstados[estado],estado,pFicha,pFichaRival, pHeuristicas);
                    break;
                }
            }
        }
        mostrarEstados(pEstados);
        if(pFicha == 1)
        {
            jugadaMia = obtenerMejorPosicion(pHeuristicas);
        }
        else
        {
            jugadaRival = obtenerMejorPosicion(pHeuristicas);
        }
    }

    private int espaciosVacios(int[][] tablero)
    {
        int espaciosVacios = 0;
        for (int i = 0; i < filas; i++)
        {
            for (int j = 0; j < columnas; j++)
            {
                if (tablero[i][j] == 0) espaciosVacios++;
            }
        }
        return espaciosVacios;
    }

    private void mostrarEstados(int[][][] estados) 
    {
        for (int estado = 0; estado < estados.length; estado++) 
        {
            System.out.print("estado nº " + estado + " ----------------\n");
            for (int i = 0; i < filas; i++) {
                for (int j = 0; j < columnas; j++) 
                {
                    System.out.print("" + estados[estado][i][j]);
                }
                System.out.print("\n");
            }
        }
    }

    private void calcularHeuristica(int x, int y, int[][] estado,int numEstado, int pFicha, int pFichaRival, int[][] pHeuristicas)
    {
        int maximoOcurrencias = 0; int maximoEncontrado = 0;
        boolean espacioVacio = false;

            //calculo el maximo horizontal
            for (int j = y-3; j <= y+3; j++)
            {
                boolean HayEspacioALaIzquierda = false;
                boolean HayEspacioALaDerecha = false;

                if(j>=0 && j<columnas)
                {
                    if (estado[x][j] == pFicha)
                    {
                        maximoOcurrencias++;
                        if (maximoOcurrencias > maximoEncontrado && !espacioVacio) 
                        {
                            maximoEncontrado = maximoOcurrencias;
                        }
                    }
                    if (estado[x][j] == lugarVacio || estado[x][j] == pFichaRival)
                    {
                        maximoOcurrencias = 0;
                        if(j>y) espacioVacio = true;

                        if(j<y && estado[x][j] == lugarVacio)
                        {
                            HayEspacioALaIzquierda=true;
                        }
                        else if(j<y && estado[x][j] == pFichaRival)
                        {
                            HayEspacioALaIzquierda=false;
                        }
                        if(j>y && estado[x][j] == lugarVacio && !espacioVacio)
                        {
                            HayEspacioALaDerecha=true;
                        }
                        else if(j>y && estado[x][j] == pFichaRival && !espacioVacio)
                        {
                            HayEspacioALaDerecha=false;
                        }
                    }
                    if(HayEspacioALaDerecha && HayEspacioALaIzquierda)
                    {
                        maximoEncontrado = maximoOcurrencias * 2;
                    }
                }
            }
           
            //calculo el maximo vertical
            espacioVacio = false;
            maximoOcurrencias = 0;
            
            for (int i = x-3; i <= x+3; i++)
            {
                boolean HayEspacioALaIzquierda = false;
                boolean HayEspacioALaDerecha = false;

                if(i>=0 && i<filas)
                {
                    if (estado[i][y] == pFicha)
                    {
                        maximoOcurrencias++;
                        if (maximoOcurrencias > maximoEncontrado && !espacioVacio) 
                        {
                            maximoEncontrado = maximoOcurrencias;
                        }
                    }
                    if (estado[i][y] == lugarVacio || estado[i][y] == pFichaRival)
                    {
                        maximoOcurrencias = 0;
                        if(i>x) espacioVacio = true;

                        if(i<x && estado[i][y] == lugarVacio)
                        {
                            HayEspacioALaIzquierda=true;
                        }
                        else if(i<x && estado[i][y] == pFichaRival)
                        {
                            HayEspacioALaIzquierda=false;
                        }
                        if(i>x && estado[i][y] == lugarVacio && !espacioVacio)
                        {
                            HayEspacioALaDerecha=true;
                        }
                        else if(i>x && estado[i][y] == pFichaRival && !espacioVacio)
                        {
                            HayEspacioALaDerecha=false;
                        }
                    }
                    if(HayEspacioALaDerecha && HayEspacioALaIzquierda)
                    {
                        maximoEncontrado = maximoOcurrencias * 2;
                    }
                }
            }
            
            //calculo el maximo en diagonal q baja
                espacioVacio = false;
                maximoOcurrencias = 0;
                
                int j = y-3;
                for (int i = x-3; i <= x+3; i++)
                {

                    if(i>=0 && i<filas && j>=0 && j<columnas)
                    {
                        if (estado[i][j] == pFicha)
                        {
                            maximoOcurrencias++;
                            if (maximoOcurrencias > maximoEncontrado && !espacioVacio) 
                            {
                                maximoEncontrado = maximoOcurrencias;
                            }
                        }
                        if (estado[i][j] == lugarVacio || estado[i][j] == pFichaRival)
                        {
                            maximoOcurrencias = 0;
                            if(i>x && j>y) espacioVacio = true;
                        }
                    }
                    j++;
                }     
            
                //calculo el maximo en diagonal q sube
                espacioVacio = false;
                maximoOcurrencias = 0;
                j = y-3;
                for (int i = x+3; i >= x-3; i--)
                {
                    if(i>=0 && i<filas && j>=0 && j<columnas)
                    {
                        if (estado[i][j] == pFicha)
                        {
                            maximoOcurrencias++;
                            if (maximoOcurrencias > maximoEncontrado && !espacioVacio) 
                            {
                                maximoEncontrado = maximoOcurrencias;
                            }
                        }
                        if (estado[i][j] == lugarVacio || estado[i][j] == pFichaRival)
                        {
                            maximoOcurrencias = 0;
                            if(i>x && j>y) espacioVacio = true;
                        }
                    }
                    j++;
                }
                
            pHeuristicas[numEstado][0] = maximoEncontrado;
            pHeuristicas[numEstado][1] = x;
            pHeuristicas[numEstado][2] = y;
            
            System.out.println("Estado nº: "+numEstado);
            System.out.println("Maximo encontrado: "+maximoEncontrado);
            System.out.println("Posicion x: "+x);
            System.out.println("Posicion y: "+y);
    }
        
    private int[] obtenerMejorPosicion(int[][] pHeuristicas)
    {
        ordenarMatriz(pHeuristicas,0,pHeuristicas.length-1);
        System.out.println("Valor heuristica: "+pHeuristicas[pHeuristicas.length-1][0]);
        System.out.println("Valor x: "+pHeuristicas[pHeuristicas.length-1][1]);
        System.out.println("Valor y: "+pHeuristicas[pHeuristicas.length-1][2]);
        
        int[] posicion = new int[3];
        posicion[0] = pHeuristicas[pHeuristicas.length-1][1];
        posicion[1] = pHeuristicas[pHeuristicas.length-1][2];
        posicion[2] = pHeuristicas[pHeuristicas.length-1][0];

        return posicion;
    }
    
    private void ordenarMatriz(int[][] matriz, int primero, int ultimo)
    {
    	int i=primero, j=ultimo;
    	int pivote=matriz[(primero+ultimo)/2][0];
    	int[] auxiliar = new int[3];
 
    	do{
    		while(matriz[i][0]<pivote) i++;    		
    		while(matriz[j][0]>pivote) j--;
 
    		if (i<=j)
                {
    			auxiliar = matriz[j];
    			matriz[j]=matriz[i];
    			matriz[i]=auxiliar;
    			i++;
    			j--;
    		}
 
    	}
        while (i<=j);
 
    	if(primero<j) ordenarMatriz(matriz,primero, j);
    	if(ultimo>i) ordenarMatriz(matriz,i, ultimo);
    }

    
}

